package com.loveprigrammer.eternity.task.wrapper;

import com.loveprigrammer.eternity.task.core.DefaultCallback;
import com.loveprigrammer.eternity.task.core.ICallback;
import com.loveprogrammer.eternity.model.game.HeroWrapper;
import com.loveprigrammer.eternity.task.core.ITask;
import com.loveprigrammer.eternity.task.work.DependWrapper;
import com.loveprigrammer.eternity.task.work.WorkResult;

import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @version 1.0.0
 * @description: 对任务的封装
 * @author: eric
 * @date: 2022-09-15 18:22
 **/
public class WorkerWrapper<T,V> {

    private String id;

    private T param;

    private ITask<T,V> task;

    private ICallback<T,V> callback;

    private List<WorkerWrapper<?,?>> nextWrappers;

    private List<DependWrapper> dependWrappers;

    /**
     * 标记该事件是否已经被处理过了，譬如已经超时返回false了，后续rpc又收到返回值了，则不再二次回调
     * 经试验,volatile并不能保证"同一毫秒"内,多线程对该值的修改和拉取
     * 单机环境下不会出现问题，主要是互联网环境下，组队任务获取会出现该问题
     * <p>
     * 1-finish, 2-error, 3-working
     */
    private AtomicInteger state = new AtomicInteger(0);

    /**
     * 该map存放所有wrapper的id和wrapper映射
     */
    private Map<String, WorkerWrapper> forParamUseWrappers;

    /**
     * 钩子变量，用来存放临时的结果
     */
    private volatile WorkResult<V> workResult = WorkResult.defaultResult();

    /**
     * 是否在执行自己前，去校验nextWrapper的执行结果<p>
     * 1   4
     * -------3
     * 2
     * 如这种在4执行前，可能3已经执行完毕了（被2执行完后触发的），那么4就没必要执行了。
     * 注意，该属性仅在nextWrapper数量<=1时有效，>1时的情况是不存在的
     */
    private volatile boolean needCheckNextWrapperResult = true;

    private WorkerWrapper(String id, T param, ITask<T, V> task, ICallback<T, V> callback) {
        if (task == null) {
            throw new NullPointerException("task is null");
        }
        this.id = id;
        this.param = param;
        this.task = task;
        //允许不设置回调
        if (callback == null) {
            callback = new DefaultCallback<>();
        }
        this.callback = callback;
    }

    private void beginTask(WorkerWrapper fromWrapper,
                       Map<String,WorkerWrapper> forParamUseWrappers,
                       HeroWrapper heroWrapper){
        this.forParamUseWrappers = forParamUseWrappers;
        // 将自己放到所有任务封装集合中去
        forParamUseWrappers.put(id,this);

        // 如果自己已经执行过了.可能有多个依赖，其中一个依赖已经执行完了，并且自己也已经开始执行或者执行完毕，
        // 当另一个依赖执行完毕，又进来该方法时，就不重复处理了
//        if(getState() == MissionState.completeTask.getCode()){
//            // TODO 获取奖励
//            getReward();
//            // 移除当前的任务
//            heroWrapper.getTaskManager().removeTask(this);
//            // TODO 开始下一个任务
//            beginNext(heroWrapper);
//            return;
//        }
//        // 如果已经结束了
//        if(getState() == MissionState.finishTask.getCode()){
//            // 开始下一个任务
//            beginNext(heroWrapper);
//            return;
//        }
//        // 如果正在进行中
//        if(getState() == MissionState.doTasking.getCode()){
//            ConsolePrint.publishMessage("任务进行中");
//            return;
//        }
//        // 无法接受任务
//        if(getState() == MissionState.cannotAccept.getCode()){
//            ConsolePrint.publishMessage("不满足条件，暂不能接受新任务");
//            return;
//        }
//        // 接受任务
//        if(getState() == MissionState.canAccept.getCode()){
//            ConsolePrint.publishMessage("接受新任务");
//            // 先移除再加入
//            heroWrapper.getTaskList().remove(this);
//            heroWrapper.getTaskList().add(this);
//            // 状态变成进行中
//            this.state.addAndGet(1);
//            doAction();
//        }
    }

    // 获取奖励
    private void getReward() {

    }

    private void doAction() {

    }

    // 开始下一个任务
    private void beginNext(HeroWrapper heroWrapper) {
        // 没有任务就结束
        if (nextWrappers == null) {
            return;
        }
        // 可能有多个后续任务
        for (WorkerWrapper<?, ?> nextWrapper : nextWrappers) {
            nextWrapper.beginTask(WorkerWrapper.this,forParamUseWrappers,heroWrapper);
        }
    }


    private int getState() {
        return state.get();
    }

}
